package ldap

import (
	"github.com/caddyserver/caddy"
	"github.com/caddyserver/caddy/caddyhttp/httpserver"
)

type LDAPConfig struct {
	Addr       string
	BindDn     string
	BindPass   string
	AuthFilter string
	BaseDn     string
	StartTLS   bool
}

func init() {
	caddy.RegisterPlugin("ldap", caddy.Plugin{
		ServerType: "http",
		Action:     Setup,
	})
}

func Setup(c *caddy.Controller) error {
	configs, err := parse(c)
	if err != nil {
		return err
	}

	newMiddleWare := func(next httpserver.Handler) httpserver.Handler {
		return &CaddyLdapHandler{
			Next:    next,
			Configs: configs,
		}
	}
	// Add middleware
	cfg := httpserver.GetConfig(c)
	cfg.AddMiddleware(newMiddleWare)

	return nil
}

func parse(c *caddy.Controller) ([]LDAPConfig, error) {
	// This parses the following config blocks
	/*
		ldap {
			path /hello
		}
	*/

	var configs []LDAPConfig

	for c.Next() {
		var ldapConfig LDAPConfig
		for c.NextBlock() {

			what := c.Val()

			switch what {
			case "addr":
				if !c.NextArg() {
					// we are expecting a value
					return nil, c.ArgErr()
				}

				ldapConfig.Addr = c.Val()

				if c.NextArg() {
					// we are expecting only one value.
					return nil, c.ArgErr()
				}
			case "bind_dn":
				if !c.NextArg() {
					// we are expecting a value
					return nil, c.ArgErr()
				}

				ldapConfig.BindDn = c.Val()
				if c.NextArg() {
					// we are expecting only one value.
					return nil, c.ArgErr()
				}
			case "bind_pass":
				if !c.NextArg() {
					// we are expecting a value
					return nil, c.ArgErr()
				}

				ldapConfig.BindPass = c.Val()
				if c.NextArg() {
					// we are expecting only one value.
					return nil, c.ArgErr()
				}
			case "auth_filter":
				if !c.NextArg() {
					// we are expecting a value
					return nil, c.ArgErr()
				}

				ldapConfig.AuthFilter = c.Val()
				if c.NextArg() {
					// we are expecting only one value.
					return nil, c.ArgErr()
				}
			case "base_dn":
				if !c.NextArg() {
					// we are expecting a value
					return nil, c.ArgErr()
				}

				ldapConfig.BaseDn = c.Val()
				if c.NextArg() {
					// we are expecting only one value.
					return nil, c.ArgErr()
				}
			case "start_tls":
				ldapConfig.StartTLS = true

			default:
				return nil, c.Errf("unsupported token_source: '%s'", what)
			}

		}

		configs = append(configs, ldapConfig)
	}
	return configs, nil
}
